package com.vcc.web.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckSafe;
import cn.hutool.core.util.ObjectUtil;
import com.vcc.core.annotations.KycReject;
import com.vcc.core.annotations.ROReject;
import com.vcc.core.annotations.RestPack;
import com.vcc.core.exception.ProgramException;
import com.vcc.data.entity.EnterpriseBeneficiary;
import com.vcc.data.entity.EnterpriseCertInfo;
import com.vcc.data.entity.EnterpriseManager;
import com.vcc.service.client.dto.kyb.EnterpriseBeneficiaryDto;
import com.vcc.service.client.dto.kyb.EnterpriseCertInfoDto;
import com.vcc.service.client.dto.kyb.EnterpriseManagerDto;
import com.vcc.service.client.dto.kyc.KycCertInfoDto;
import com.vcc.service.client.vo.kyc.KycCertInfoVo;
import com.vcc.service.client.vo.kyc.KycVo;
import com.vcc.service.client.vo.kyc.kyb.EnterpriseBeneficiaryVo;
import com.vcc.service.client.vo.kyc.kyb.EnterpriseCertInfoVo;
import com.vcc.service.client.vo.kyc.kyb.EnterpriseManagerVo;
import com.vcc.service.service.*;
import com.vcc.web.core.component.OssComponent;
import com.vcc.web.core.util.UserUtil;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;

@Log4j2
@RestController
@RequestMapping("kyc")
public class KycController {

    @Autowired
    private KycCertInfoService kycCertInfoService;
    @Autowired
    private KycSuccessCertInfoService kycSuccessCertInfoService;
    @Autowired
    private UserService userService;
    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private EnterpriseCertInfoService enterpriseCertInfoService;
    @Autowired
    private EnterpriseManagerService enterpriseManagerService;
    @Autowired
    private EnterpriseBeneficiaryService enterpriseBeneficiaryService;
    @Autowired
    private OssComponent ossComponent;
    @Autowired
    private ClientParamService clientParamService;


    @RestPack
    @PostMapping("clearKyc")
    @SaCheckLogin
    @SaCheckSafe("CLEAR_KYC")
    public boolean clearKyc() {
        Long userId = UserUtil.getId();
        kycCertInfoService.removeByUserId(userId);
        enterpriseCertInfoService.removeByUserId(userId);
        return true;
    }


    @RestPack
    @GetMapping("get")
    public KycVo get() {
        Long userId = UserUtil.getId();
        String clientUserFlag = clientParamService.getValueByCodeAndUserIdOrDefaultValue("HAS_PERSONAL", userId, "true");
        if (clientUserFlag.equals("false")) {
            return KycVo.builder()
                    .flag(true)
                    .build();
        }
        Boolean userKyc = kycCertInfoService.existsByUserId(userId);

        KycCertInfoVo certInfoVo = null;
        if (userKyc) {
            certInfoVo = kycCertInfoService.getByUserId(userId);
            if (StringUtils.isNotBlank(certInfoVo.getCertImgFront())) {
                certInfoVo.setCertImgFrontUrl(ossComponent.generateTokenUrl(certInfoVo.getCertImgFront()).toString());
            }
            if (StringUtils.isNotBlank(certInfoVo.getCertImgBack())) {
                certInfoVo.setCertImgBackUrl(ossComponent.generateTokenUrl(certInfoVo.getCertImgBack()).toString());
            }
            if (StringUtils.isNotBlank(certInfoVo.getCertImgHand())) {
                certInfoVo.setCertImgHandUrl(ossComponent.generateTokenUrl(certInfoVo.getCertImgHand()).toString());
            }
        }
        Boolean enterpriseKyb = enterpriseCertInfoService.existsByUserId(userId);
        EnterpriseCertInfoVo enterpriseCertInfoVo = null;
        if (enterpriseKyb) {
            enterpriseCertInfoVo = enterpriseCertInfoService.getEnterpriseCertInfoVoByUserId(userId);
            if (StringUtils.isNotBlank(enterpriseCertInfoVo.getRegistrationCertImg())) {
                enterpriseCertInfoVo.setRegistrationCertImgUrl(ossComponent.generateTokenUrl(enterpriseCertInfoVo.getRegistrationCertImg()).toString());
            }
            if (StringUtils.isNotBlank(enterpriseCertInfoVo.getLicenseImg())) {
                enterpriseCertInfoVo.setLicenseImgUrl(ossComponent.generateTokenUrl(enterpriseCertInfoVo.getLicenseImg()).toString());
            }
            if (StringUtils.isNotBlank(enterpriseCertInfoVo.getAnnualReportImg())) {
                enterpriseCertInfoVo.setAnnualReportImgUrl(ossComponent.generateTokenUrl(enterpriseCertInfoVo.getAnnualReportImg()).toString());
            }
            for (EnterpriseBeneficiaryVo beneficiary : enterpriseCertInfoVo.getBeneficiaries()) {
                if (StringUtils.isNotBlank(beneficiary.getCertImgFont())) {
                    beneficiary.setCertImgFontUrl(ossComponent.generateTokenUrl(beneficiary.getCertImgFont()).toString());
                }
                if (StringUtils.isNotBlank(beneficiary.getCertImgBack())) {
                    beneficiary.setCertImgBackUrl(ossComponent.generateTokenUrl(beneficiary.getCertImgBack()).toString());
                }
                if (StringUtils.isNotBlank(beneficiary.getEquityStructureImg())) {
                    beneficiary.setEquityStructureImgUrl(ossComponent.generateTokenUrl(beneficiary.getEquityStructureImg()).toString());
                }
            }
            for (EnterpriseManagerVo manager : enterpriseCertInfoVo.getManagers()) {
                if (StringUtils.isNotBlank(manager.getCertImgFont())) {
                    manager.setCertImgFontUrl(ossComponent.generateTokenUrl(manager.getCertImgFont()).toString());
                }
                if (StringUtils.isNotBlank(manager.getCertImgBack())) {
                    manager.setCertImgBackUrl(ossComponent.generateTokenUrl(manager.getCertImgBack()).toString());
                }
            }
        }

        return KycVo.builder()
                .kycStatus(userKyc)
                .kybStatus(enterpriseKyb)
                .kycCertInfoVo(certInfoVo)
                .enterpriseCertInfoVo(enterpriseCertInfoVo)
                .build();
    }

    @ROReject
    @RestPack
    @PostMapping("requestKyc")
    @SaCheckLogin
    public Boolean requestKyc(@RequestBody KycCertInfoDto kycCertInfoDto) {
        RLock lock = redissonClient.getLock("kyc:requestKyc:" + UserUtil.getId());
        try {
            boolean tryLock = lock.tryLock();
            if (!tryLock) {
                throw new ProgramException("请勿重复提交");
            }
            return kycCertInfoService.requestCert(kycCertInfoDto, UserUtil.getId());
        } catch (Exception e) {
            if (e instanceof ProgramException) {
                throw e;
            }
            throw new ProgramException("提交认证资料失败，请稍后再试");
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    @ROReject
    @RestPack
    @PostMapping("requestKyb")
    @SaCheckLogin
    public Boolean requestKyb(@RequestBody EnterpriseCertInfoDto enterpriseCertInfoDto) {
        RLock lock = redissonClient.getLock("kyc:requestKyc:" + UserUtil.getId());
        try {
            boolean tryLock = lock.tryLock();
            if (!tryLock) {
                throw new ProgramException("请勿重复提交");
            }
            if (enterpriseCertInfoDto.getStep() == 1) {
                if (StringUtils.isBlank(enterpriseCertInfoDto.getRegisterCountry())) {
                    throw new ProgramException("企业注册地区不能为空");
                }
                try {
                    EnterpriseCertInfo enterpriseCertInfo = enterpriseCertInfoService.getByUserId(UserUtil.getId());
                    if (enterpriseCertInfo.getStep() == 6) {
                        throw new ProgramException("您已经提交过企业认证资料，请勿重复提交");
                    }
                    if (enterpriseCertInfo.getStep() == 7 && enterpriseCertInfo.getStatus() != 1) {
                        throw new ProgramException("您当前审核资料无法提交，请勿重复提交");
                    }
                    enterpriseCertInfo.setRegisterCountry(enterpriseCertInfoDto.getRegisterCountry());
                    enterpriseCertInfo.setStep(1);
                    enterpriseCertInfo.setStatus(2);
                    enterpriseCertInfoService.updateById(enterpriseCertInfo);
                } catch (Exception e) {
                    if (e instanceof ProgramException) {
                        throw e;
                    }
                    EnterpriseCertInfo enterpriseCertInfo = EnterpriseCertInfo.builder()
                            .userId(UserUtil.getId())
                            .registerCountry(enterpriseCertInfoDto.getRegisterCountry())
                            .step(1)
                            .status(2)
                            .requestDate(new Date())
                            .build();
                    enterpriseCertInfoService.save(enterpriseCertInfo);
                }

            } else if (enterpriseCertInfoDto.getStep() == 2) {
                if (!enterpriseCertInfoDto.getHasOperateAddressSame()) {
                    if (StringUtils.isBlank(enterpriseCertInfoDto.getOperateCountry())) {
                        throw new ProgramException("经营国家不能为空");
                    }
                    if (StringUtils.isBlank(enterpriseCertInfoDto.getOperateAddress())) {
                        throw new ProgramException("经营地址不能为空");
                    }
                }
                if (StringUtils.isBlank(enterpriseCertInfoDto.getRegisterAddress())) {
                    throw new ProgramException("注册地址不能为空");
                }
                if (StringUtils.isBlank(enterpriseCertInfoDto.getRegisterDate())) {
                    throw new ProgramException("注册时间不能为空");
                }
                //公司注册号必须要
                if (StringUtils.isBlank(enterpriseCertInfoDto.getRegistrationNumber())) {
                    throw new ProgramException("公司注册号不能为空");
                }
                //英文名必须要
                if (StringUtils.isBlank(enterpriseCertInfoDto.getCompanyNameEn())) {
                    throw new ProgramException("公司英文名不能为空");
                }
                //registrationCertImg 不能为空
                if (StringUtils.isBlank(enterpriseCertInfoDto.getRegistrationCertImg())) {
                    throw new ProgramException("公司注册证明文件不能为空");
                }
                EnterpriseCertInfo enterpriseCertInfo = enterpriseCertInfoService.getByUserId(UserUtil.getId());

                if (enterpriseCertInfo.getRegisterCountry().equals("HK")) {
                    //香港的公司名必须要
                    if (StringUtils.isBlank(enterpriseCertInfoDto.getCompanyNameCn())) {
                        throw new ProgramException("公司中文名不能为空");
                    }
                    //商业登记证号码
                    if (StringUtils.isBlank(enterpriseCertInfoDto.getLicenseCode())) {
                        throw new ProgramException("商业登记证号码不能为空");
                    }
                    if (StringUtils.isBlank(enterpriseCertInfoDto.getLicenseImg())) {
                        throw new ProgramException("商业登记证图片不能为空");
                    }
                    if (StringUtils.isBlank(enterpriseCertInfoDto.getAnnualReportImg())) {
                        throw new ProgramException("周年申报表图片不能为空");
                    }
                    if (ObjectUtil.isNull(enterpriseCertInfoDto.getHasLongTerm())) {
                        throw new ProgramException("证件是否长期有效不能为空");
                    }
                    if (!enterpriseCertInfoDto.getHasLongTerm() && StringUtils.isBlank(enterpriseCertInfoDto.getExpireDate())) {
                        throw new ProgramException("证件有效期不能为空");
                    }
                }
                enterpriseCertInfo.setCompanyNameCn(enterpriseCertInfoDto.getCompanyNameCn());
                enterpriseCertInfo.setCompanyNameEn(enterpriseCertInfoDto.getCompanyNameEn());
                enterpriseCertInfo.setLicenseCode(enterpriseCertInfoDto.getLicenseCode());
                enterpriseCertInfo.setRegistrationNumber(enterpriseCertInfoDto.getRegistrationNumber());
                enterpriseCertInfo.setRegisterAddress(enterpriseCertInfoDto.getRegisterAddress());
                enterpriseCertInfo.setRegisterDate(enterpriseCertInfoDto.getRegisterDate());
                enterpriseCertInfo.setHasLongTerm(enterpriseCertInfoDto.getHasLongTerm());
                enterpriseCertInfo.setExpireDate(enterpriseCertInfoDto.getExpireDate());
                enterpriseCertInfo.setHasOperateAddressSame(enterpriseCertInfoDto.getHasOperateAddressSame());
                enterpriseCertInfo.setOperateCountry(enterpriseCertInfoDto.getOperateCountry());
                enterpriseCertInfo.setOperateAddress(enterpriseCertInfoDto.getOperateAddress());
                enterpriseCertInfo.setAnnualReportImg(enterpriseCertInfoDto.getAnnualReportImg());
                enterpriseCertInfo.setLicenseImg(enterpriseCertInfoDto.getLicenseImg());
                enterpriseCertInfo.setRegistrationCertImg(enterpriseCertInfoDto.getRegistrationCertImg());
                enterpriseCertInfo.setStep(2);
                enterpriseCertInfo.setStatus(2);
                enterpriseCertInfoService.updateById(enterpriseCertInfo);
            } else if (enterpriseCertInfoDto.getStep() == 3) {
                //industryType 必须要
                if (StringUtils.isBlank(enterpriseCertInfoDto.getIndustryType())) {
                    throw new ProgramException("行业类别不能为空");
                }
                //businessAddress 必须要
                if (StringUtils.isBlank(enterpriseCertInfoDto.getBusinessAddress())) {
                    throw new ProgramException("业务地址不能为空");
                }
                EnterpriseCertInfo enterpriseCertInfo = enterpriseCertInfoService.getByUserId(UserUtil.getId());
                enterpriseCertInfo.setBusinessAddress(enterpriseCertInfoDto.getBusinessAddress());
                enterpriseCertInfo.setIndustryType(enterpriseCertInfoDto.getIndustryType());
                enterpriseCertInfo.setStep(3);
                enterpriseCertInfo.setStatus(2);
                enterpriseCertInfoService.updateById(enterpriseCertInfo);
            } else if (enterpriseCertInfoDto.getStep() == 4) {
                //industryType 必须要
                List<EnterpriseManagerDto> managers = enterpriseCertInfoDto.getEnterpriseManagers();
                if (managers == null || managers.isEmpty()) {
                    throw new ProgramException("董事信息不能为空");
                }
                for (EnterpriseManagerDto manager : managers) {
                    if (StringUtils.isBlank(manager.getFirstName())) {
                        throw new ProgramException("董事姓名不能为空");
                    }
                    if (StringUtils.isBlank(manager.getLastName())) {
                        throw new ProgramException("董事姓氏不能为空");
                    }
                    if (StringUtils.isBlank(manager.getCertType())) {
                        throw new ProgramException("董事证件类型不能为空");
                    }
                    if (StringUtils.isBlank(manager.getIssuePlace())) {
                        throw new ProgramException("董事证件发放地不能为空");
                    }
                    if (StringUtils.isBlank(manager.getCertImgFont())) {
                        throw new ProgramException("董事证件正面照片不能为空");
                    }
                    if (StringUtils.isBlank(manager.getCertImgBack())) {
                        throw new ProgramException("董事证件背面照片不能为空");
                    }
                }
                EnterpriseCertInfo enterpriseCertInfo = enterpriseCertInfoService.getByUserId(UserUtil.getId());
                enterpriseManagerService.removeByEnterpriseCertInfoId(enterpriseCertInfo.getId());
                enterpriseCertInfo.setStep(4);
                enterpriseCertInfo.setStatus(2);
                enterpriseCertInfoService.updateById(enterpriseCertInfo);
                managers.forEach(manager -> {
                    EnterpriseManager enterpriseManager = new EnterpriseManager();
                    enterpriseManager.setEnterpriseCertInfoId(enterpriseCertInfo.getId());
                    enterpriseManager.setFirstName(manager.getFirstName());
                    enterpriseManager.setLastName(manager.getLastName());
//                    enterpriseManager.setMiddleName(manager.getMiddleName());
//                    enterpriseManager.setGender(manager.getGender());
                    enterpriseManager.setCertType(manager.getCertType());
//                    enterpriseManager.setBirthDate(manager.getBirthDate());
//                    enterpriseManager.setCertNo(manager.getCertNo());
                    enterpriseManager.setIssuePlace(manager.getIssuePlace());
//                    enterpriseManager.setHasLongTerm(manager.getHasLongTerm());
//                    enterpriseManager.setExpireDate(manager.getExpireDate());
                    enterpriseManager.setCertImgFont(manager.getCertImgFont());
                    enterpriseManager.setCertImgBack(manager.getCertImgBack());
//                    enterpriseManager.setResidenceAddress(manager.getResidenceAddress());
//                    enterpriseManager.setResidenceCountry(manager.getResidenceCountry());
                    enterpriseManagerService.save(enterpriseManager);
                });
            } else if (enterpriseCertInfoDto.getStep() == 5) {
                //industryType 必须要
                List<EnterpriseBeneficiaryDto> beneficiaries = enterpriseCertInfoDto.getEnterpriseBeneficiaries();
                if (beneficiaries == null || beneficiaries.isEmpty()) {
                    throw new ProgramException("董事信息不能为空");
                }
                for (EnterpriseBeneficiaryDto enterpriseBeneficiary : beneficiaries) {
                    if (enterpriseBeneficiary.getType() == null || enterpriseBeneficiary.getType() < 0 || enterpriseBeneficiary.getType() > 2) {
                        throw new ProgramException("受益人类型错误");
                    }
                    if (enterpriseBeneficiary.getType() == 0) {
                        if (StringUtils.isBlank(enterpriseBeneficiary.getFirstName())) {
                            throw new ProgramException("董事姓名不能为空");
                        }
                        if (StringUtils.isBlank(enterpriseBeneficiary.getLastName())) {
                            throw new ProgramException("董事姓氏不能为空");
                        }
                        if (StringUtils.isBlank(enterpriseBeneficiary.getCertType())) {
                            throw new ProgramException("董事证件类型不能为空");
                        }
                        if (StringUtils.isBlank(enterpriseBeneficiary.getIssuePlace())) {
                            throw new ProgramException("董事证件发放地不能为空");
                        }
                        if (StringUtils.isBlank(enterpriseBeneficiary.getCertImgFont())) {
                            throw new ProgramException("董事证件正面照片不能为空");
                        }
                        if (StringUtils.isBlank(enterpriseBeneficiary.getCertImgBack())) {
                            throw new ProgramException("董事证件背面照片不能为空");
                        }
                    } else {
                        if (StringUtils.isBlank(enterpriseBeneficiary.getCompanyName())) {
                            throw new ProgramException("受益人公司英文名不能为空");
                        }
                        if (StringUtils.isBlank(enterpriseBeneficiary.getEquityStructureImg())) {
                            throw new ProgramException("受益人公司股权架构不能为空");
                        }
                    }
                }
                EnterpriseCertInfo enterpriseCertInfo = enterpriseCertInfoService.getByUserId(UserUtil.getId());
                enterpriseBeneficiaryService.removeByEnterpriseCertInfoId(enterpriseCertInfo.getId());
                enterpriseCertInfo.setStep(6);
                enterpriseCertInfo.setStatus(2);
                enterpriseCertInfoService.updateById(enterpriseCertInfo);
                beneficiaries.forEach(beneficiarie -> {
                    EnterpriseBeneficiary enterpriseBeneficiary = new EnterpriseBeneficiary();
                    enterpriseBeneficiary.setType(beneficiarie.getType());
                    if (beneficiarie.getType() == 0) {
                        enterpriseBeneficiary.setEnterpriseCertInfoId(enterpriseCertInfo.getId());
                        enterpriseBeneficiary.setFirstName(beneficiarie.getFirstName());
                        enterpriseBeneficiary.setLastName(beneficiarie.getLastName());
                        enterpriseBeneficiary.setCertType(beneficiarie.getCertType());
                        enterpriseBeneficiary.setIssuePlace(beneficiarie.getIssuePlace());
                        enterpriseBeneficiary.setCertImgFont(beneficiarie.getCertImgFont());
                        enterpriseBeneficiary.setCertImgBack(beneficiarie.getCertImgBack());
                    } else {
                        enterpriseBeneficiary.setEnterpriseCertInfoId(enterpriseCertInfo.getId());
                        enterpriseBeneficiary.setCompanyName(beneficiarie.getCompanyName());
                        enterpriseBeneficiary.setEquityStructureImg(beneficiarie.getEquityStructureImg());
                    }
                    enterpriseBeneficiaryService.save(enterpriseBeneficiary);
                });
            } else {
                throw new ProgramException("未知的企业认证步骤");
            }
        } catch (Exception e) {
            log.error("提交企业认证资料失败", e);
            if (e instanceof ProgramException) {
                throw e;
            }
            throw new ProgramException("提交认证资料失败，请稍后再试");
        } finally {
            if (lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return true;
    }
}
